import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
	state: {
		m1: 1,
		m2: 1,
		l1: 1,
		l2: 1,
		g: 9.8,
		initialTheta1: 120,
		initialOmega1: 0,
		initialTheta2: 60,
		initialOmega2: 0,
		timeRange: 10,
		stepLength: 0.0001,
		roughTheta1: [],
		roughOmega1: [],
		roughTheta2: [],
		roughOmega2: [],
		innerBallPosition: [],
		outerBallPosition: [],
		showInnerBallTrack: true,
		showOuterBallTrack: true,
		timer: null,
		isRunningNow: false,
	},
	mutations: {
		m1(state, value) {
			state.m1 = value
		},

		m2(state, value) {
			state.m2 = value
		},

		l1(state, value) {
			state.l1 = value
		},

		l2(state, value) {
			state.l2 = value
		},

		g(state, value) {
			state.g = value
		},

		initialTheta1(state, value) {
			state.initialTheta1 = value
		},

		initialTheta2(state, value) {
			state.initialTheta2 = value
		},

		initialOmega1(state, value) {
			state.initialOmega1 = value
		},

		initialOmega2(state, value) {
			state.initialOmega2 = value
		},

		timeRange(state, value) {
			state.timeRange = value
		},

		stepLength(state, value) {
			state.stepLength = value
		},
		
		startSimulation(state) {
			clearInterval(state.timer)
			state.isRunningNow = true
			this.commit('clearData')
			this.commit('generateData')
			this.commit('draw')
		},

		generateData(state) {

			var m1 = state.m1;
			var m2 = state.m2;
			var l1 = state.l1;
			var l2 = state.l2;
			var g = state.g;

			var initialTheta1 = state.initialTheta1 / 180 * Math.PI;
			var initialOmega1 = state.initialOmega1 / 180 * Math.PI;
			var initialTheta2 = state.initialTheta2 / 180 * Math.PI;
			var initialOmega2 = state.initialOmega2 / 180 * Math.PI;

			var y1 = [];
			var y2 = [];
			var y3 = [];
			var y4 = [];

			y1[0] = [0, initialTheta1];
			y2[0] = [0, initialOmega1];
			y3[0] = [0, initialTheta2];
			y4[0] = [0, initialOmega2];

			var k1_1 = 0;
			var k1_2 = 0;
			var k1_3 = 0;
			var k1_4 = 0;

			var k2_1 = 0;
			var k2_2 = 0;
			var k2_3 = 0;
			var k2_4 = 0;

			var k3_1 = 0;
			var k3_2 = 0;
			var k3_3 = 0;
			var k3_4 = 0;

			var k4_1 = 0;
			var k4_2 = 0;
			var k4_3 = 0;
			var k4_4 = 0;

			var h = state.stepLength;
			var timeRange = state.timeRange;

			for (let i = 0; i < timeRange / h; i++) {
				k1_1 = y2[i][1];
				k1_2 = y2[i][1] + h / 2 * k1_1;
				k1_3 = y2[i][1] + h / 2 * k1_2;
				k1_4 = y2[i][1] + h * k1_3;
				y1[i + 1] = [(i + 1) * h, y1[i][1] + h / 6 * (k1_1 + 2 * k1_2 + 2 * k1_3 + k1_4)];

				k2_1 = (m2 * Math.cos(y1[i][1] - y3[i][1]) * (g * Math.sin(y3[i][1]) - l1 *
					Math.sin(y1[i][1] - y3[i][1]) * Math.pow(y2[i][1], 2)) / (l1 * m1 + l1 *
						m2 - l1 * m2 * Math.pow(Math.cos(y1[i][1] - y3[i][1]), 2)) - (g * Math.sin(
							y1[i][1]) * (m1 + m2) + l2 * m2 * Math.sin(y1[i][1] - y3[i][1]) * Math
								.pow(y4[i][1], 2)) / (l1 * m1 + l1 * m2 - l1 * m2 * Math.pow(Math.cos(
									y1[i][1] - y3[i][1]), 2)));
				k2_2 = (m2 * Math.cos((y1[i][1] + h / 2 * k2_1) - (y3[i][1] + h / 2 * k2_1)) * (g *
					Math.sin(y3[i][1] + h / 2 * k2_1) - l1 * Math.sin((y1[i][1] + h / 2 * k2_1) - (y3[i][1] +
						h / 2 * k2_1)) * Math.pow((y2[i][1] + h / 2 * k2_1), 2)) / (l1 * m1 + l1 * m2 -
							l1 * m2 * Math.pow(Math.cos((y1[i][1] + h / 2 * k2_1) - (y3[i][1] + h / 2 * k2_1)), 2)
					) - (g * Math.sin(y1[i][1] + h / 2 * k2_1) * (m1 + m2) + l2 * m2 * Math.sin((
						y1[i][1] + h / 2 * k2_1) - (y3[i][1] + h / 2 * k2_1)) * Math.pow((y4[i][1] + h / 2 * k2_1),
							2)) / (l1 * m1 + l1 * m2 - l1 * m2 * Math.pow(Math.cos((y1[i][1] + h /
								2 * k2_1) - (y3[i][1] + h / 2 * k2_1)), 2)));
				k2_3 = (m2 * Math.cos((y1[i][1] + h / 2 * k2_2) - (y3[i][1] + h / 2 * k2_2)) * (g *
					Math.sin(y3[i][1] + h / 2 * k2_2) - l1 * Math.sin((y1[i][1] + h / 2 * k2_2) - (y3[i][1] +
						h / 2 * k2_2)) * Math.pow((y2[i][1] + h / 2 * k2_2), 2)) / (l1 * m1 + l1 * m2 -
							l1 * m2 * Math.pow(Math.cos((y1[i][1] + h / 2 * k2_2) - (y3[i][1] + h / 2 * k2_2)), 2)
					) - (g * Math.sin(y1[i][1] + h / 2 * k2_2) * (m1 + m2) + l2 * m2 * Math.sin((
						y1[i][1] + h / 2 * k2_2) - (y3[i][1] + h / 2 * k2_2)) * Math.pow((y4[i][1] + h / 2 * k2_2),
							2)) / (l1 * m1 + l1 * m2 - l1 * m2 * Math.pow(Math.cos((y1[i][1] + h /
								2 * k2_2) - (y3[i][1] + h / 2 * k2_2)), 2)));
				k2_4 = (m2 * Math.cos((y1[i][1] + h * k2_3) - (y3[i][1] + h * k2_3)) * (g * Math.sin(
					y3[i][1] + h * k2_3) - l1 * Math.sin((y1[i][1] + h * k2_3) - (y3[i][1] + h * k2_3)) *
					Math.pow((y2[i][1] + h * k2_3), 2)) / (l1 * m1 + l1 * m2 - l1 * m2 *
						Math.pow(Math.cos((y1[i][1] + h * k2_3) - (y3[i][1] + h * k2_3)), 2)) - (g * Math.sin(y1[
							i][1] + h * k2_3) * (m1 + m2) + l2 * m2 * Math.sin((y1[i][1] + h * k2_3) - (
								y3[i][1] + h * k2_3)) * Math.pow((y4[i][1] + h * k2_3), 2)) / (l1 * m1 + l1 * m2 -
									l1 * m2 * Math.pow(Math.cos((y1[i][1] + h * k2_3) - (y3[i][1] + h * k2_3)), 2)));
				y2[i + 1] = [(i + 1) * h, y2[i][1] + h / 6 * (k2_1 + 2 * k2_2 + 2 * k2_3 + k2_4)];

				k3_1 = y4[i][1];
				k3_2 = y4[i][1] + h / 2 * k3_1;
				k3_3 = y4[i][1] + h / 2 * k3_2;
				k3_4 = y4[i][1] + h * k3_3;
				y3[i + 1] = [(i + 1) * h, y3[i][1] + h / 6 * (k3_1 + 2 * k3_2 + 2 * k3_3 + k3_4)];

				k4_1 = (Math.cos(y1[i][1] - y3[i][1]) * (g * Math.sin(y1[i][1]) * (m1 + m2) +
					l2 * m2 * Math.sin(y1[i][1] - y3[i][1]) * Math.pow(y4[i][1], 2))) / (l2 *
						m1 + l2 * m2 - l2 * m2 * Math.pow(Math.cos(y1[i][1] - y3[i][1]), 2)) - (
							(m1 + m2) * (g * Math.sin(y3[i][1]) - l1 * Math.sin(y1[i][1] - y3[i][1]) *
								Math.pow(y2[i][1], 2))) / (l2 * m1 + l2 * m2 - l2 * m2 * Math.pow(Math.cos(
									y1[i][1] - y3[i][1]), 2));
				k4_2 = (Math.cos((y1[i][1] + h / 2 * k4_1) - (y3[i][1] + h / 2 * k4_1)) * (g * Math.sin((
					y1[i][1] + h / 2 * k4_1)) * (m1 + m2) + l2 * m2 * Math.sin((y1[i][1] + h /
						2 * k4_1) - (y3[i][1] + h / 2 * k4_1)) * Math.pow((y4[i][1] + h / 2 * k4_1), 2))) / (l2 *
							m1 + l2 * m2 - l2 * m2 * Math.pow(Math.cos((y1[i][1] + h / 2 * k4_1) - (y3[
								i][1] + h / 2 * k4_1)), 2)) - ((m1 + m2) * (g * Math.sin((y3[i][1] + h / 2 * k4_1)) -
									l1 * Math.sin((y1[i][1] + h / 2 * k4_1) - (y3[i][1] + h / 2 * k4_1)) * Math.pow((y2[i]
									[1] + h / 2 * k4_1), 2))) / (l2 * m1 + l2 * m2 - l2 * m2 * Math.pow(Math.cos(
										(y1[i][1] + h / 2 * k4_1) - (y3[i][1] + h / 2 * k4_1)), 2));
				k4_3 = (Math.cos((y1[i][1] + h / 2 * k4_2) - (y3[i][1] + h / 2 * k4_2)) * (g * Math.sin((
					y1[i][1] + h / 2 * k4_2)) * (m1 + m2) + l2 * m2 * Math.sin((y1[i][1] + h /
						2 * k4_2) - (y3[i][1] + h / 2 * k4_2)) * Math.pow((y4[i][1] + h / 2 * k4_2), 2))) / (l2 *
							m1 + l2 * m2 - l2 * m2 * Math.pow(Math.cos((y1[i][1] + h / 2 * k4_2) - (y3[
								i][1] + h / 2 * k4_2)), 2)) - ((m1 + m2) * (g * Math.sin((y3[i][1] + h / 2 * k4_2)) -
									l1 * Math.sin((y1[i][1] + h / 2 * k4_2) - (y3[i][1] + h / 2 * k4_2)) * Math.pow((y2[i]
									[1] + h / 2 * k4_2), 2))) / (l2 * m1 + l2 * m2 - l2 * m2 * Math.pow(Math.cos(
										(y1[i][1] + h / 2 * k4_2) - (y3[i][1] + h / 2 * k4_2)), 2));
				k4_4 = (Math.cos((y1[i][1] + h * k4_3) - (y3[i][1] + h * k4_3)) * (g * Math.sin((y1[i]
				[1] + h * k4_3)) * (m1 + m2) + l2 * m2 * Math.sin((y1[i][1] + h * k4_3) - (y3[
					i][1] + h * k4_3)) * Math.pow((y4[i][1] + h * k4_3), 2))) / (l2 * m1 + l2 * m2 -
						l2 * m2 * Math.pow(Math.cos((y1[i][1] + h * k4_3) - (y3[i][1] + h * k4_3)), 2)) - ((
							m1 + m2) * (g * Math.sin((y3[i][1] + h * k4_3)) - l1 * Math.sin((y1[i][1] +
								h * k4_3) - (y3[i][1] + h * k4_3)) * Math.pow((y2[i][1] + h * k4_3), 2))) / (l2 * m1 +
									l2 * m2 - l2 * m2 * Math.pow(Math.cos((y1[i][1] + h * k4_3) - (y3[i][1] + h *
										k4_3)), 2));
				y4[i + 1] = [(i + 1) * h, y4[i][1] + h / 6 * (k4_1 + 2 * k4_2 + 2 * k4_3 + k4_4)];
			};

			var innerBallPosition = [];
			var outerBallPosition = [];

			var roughTheta1 = [];
			var roughOmega1 = [];
			var roughTheta2 = [];
			var roughOmega2 = [];

			// 由于原始数据过度密集，导致绘制曲线困难，下面将绘制曲线的数据进行稀释，加速绘图速度。
			for (let j = 0; j < timeRange / h; j += 100) {

				roughTheta1.push([j * h, y1[j][1] / Math.PI * 180]);
				roughOmega1.push([j * h, y2[j][1] / Math.PI * 180]);
				roughTheta2.push([j * h, y3[j][1] / Math.PI * 180]);
				roughOmega2.push([j * h, y4[j][1] / Math.PI * 180]);

				innerBallPosition[j / 100] = [l1 * Math.sin(y1[j][1]), -l1 * Math.cos(y1[j][1])];
				outerBallPosition[j / 100] = [l1 * Math.sin(y1[j][1]) + l2 * Math.sin(y3[j][1]), -l1 * Math.cos(y1[j][1]) - l2 *
					Math.cos(y3[j][1])
				];
			};

			state.roughTheta1 = roughTheta1;
			state.roughOmega1 = roughOmega1;
			state.roughTheta2 = roughTheta2;
			state.roughOmega2 = roughOmega2;

			state.innerBallPosition = innerBallPosition;
			state.outerBallPosition = outerBallPosition;
		},

		draw(state) {

			setTimeout(() => {
				var echarts = require('echarts')
				var drawArea = echarts.init(document.querySelector("#drawArea"))

				var l1 = state.l1;
				var l2 = state.l2;

				var option = {
					animation: false,
					xAxis: {
						min: -1.05 * (l1 + l2),
						max: 1.05 * (l1 + l2),
						show: false
					},
					yAxis: {
						min: -1.05 * (l1 + l2),
						max: 1.05 * (l1 + l2),
						show: false
					},
					series: [{
						name: 'innerLine',
						showSymbol: false,
						type: 'line',
						lineStyle: {
							width: 3,
							color: "green"
						},
						data: innerLine,

					},
					{
						name: 'innerBallOutline',
						showSymbol: false,
						type: 'line',
						lineStyle: {
							width: 3,
							color: "red"
						},
						data: innerBallOutline,

					},
					{
						name: 'innerBallTrack',
						showSymbol: false,
						type: 'line',
						lineStyle: {
							width: 1,
							color: "red"
						},
						data: innerBallTrack,

					},
					{
						name: 'outerLine',
						showSymbol: false,
						type: 'line',
						lineStyle: {
							width: 3,
							color: "green"
						},
						data: outerLine,

					},
					{
						name: 'outerBallOutline',
						showSymbol: false,
						type: 'line',
						lineStyle: {
							width: 3,
							color: "orange"
						},
						data: outerBallOutline,
					},
					{
						name: 'outerBallTrack',
						showSymbol: false,
						type: 'line',
						lineStyle: {
							width: 1,
							color: "orange"
						},
						data: outerBallTrack,
					}
					]
				};

				var n = 0;
				var r = 0.05 * (l1 + l2);
				var timeRange = state.timeRange;

				var innerLine = [];
				var outerLine = [];
				var innerBallTrack = [];
				var outerBallTrack = [];
				var innerBallOutline = [];
				var outerBallOutline = [];

				var innerBallPosition = state.innerBallPosition;
				var outerBallPosition = state.outerBallPosition;

				clearInterval(state.timer);

				state.timer = setInterval(() => {

					innerBallOutline = [];
					outerBallOutline = [];

					for (let t = 0; t <= 2 * Math.PI; t += 0.01) {
						innerBallOutline.push([innerBallPosition[n][0] + r * Math.cos(t), innerBallPosition[n][1] + r * Math.sin(t)]);
						outerBallOutline.push([outerBallPosition[n][0] + r * Math.cos(t), outerBallPosition[n][1] + r * Math.sin(t)]);
					};

					innerLine = [
						[0, 0],
						[innerBallPosition[n][0], innerBallPosition[n][1]]
					];
					outerLine = [
						[innerBallPosition[n][0], innerBallPosition[n][1]],
						[outerBallPosition[n][0], outerBallPosition[n][1]]
					];

					innerBallTrack.push([innerBallPosition[n][0], innerBallPosition[n][1]]);
					outerBallTrack.push([outerBallPosition[n][0], outerBallPosition[n][1]]);

					option.series[0].data = innerLine;
					option.series[1].data = innerBallOutline;
					option.series[2].data = innerBallTrack;
					option.series[3].data = outerLine;
					option.series[4].data = outerBallOutline;
					option.series[5].data = outerBallTrack;

					drawArea.setOption(option);

					n += innerBallPosition.length / timeRange * 0.01;

					if (n >= innerBallPosition.length) {
						clearInterval(state.timer);
						state.isRunningNow = false;
					};
				}, 10);
			}, 20)
		},

		drawData(state) {

			setTimeout(() => {
				var echarts = require("echarts");
				var dataPage = echarts.init(document.querySelector("#dataPage"));

				var roughTheta1 = state.roughTheta1;
				var roughOmega1 = state.roughOmega1;
				var roughTheta2 = state.roughTheta2;
				var roughOmega2 = state.roughOmega2;

				var option = {
					legend: {
						right: 60,
						top: 30,
						itemHeight: 20,
						selected: {
							θ1: true,
							θ2: true,
							ω1: false,
							ω2: false,
						},
					},
					xAxis: {},
					yAxis: {},
					series: [
						{
							name: "θ1",
							showSymbol: false,
							type: "line",
							lineStyle: {
								width: 2,
								color: "red",
							},
							data: roughTheta1,
						},
						{
							name: "θ2",
							showSymbol: false,
							type: "line",
							lineStyle: {
								width: 2,
								color: "orange",
							},
							data: roughTheta2,
						},
						{
							name: "ω1",
							showSymbol: false,
							type: "line",
							lineStyle: {
								width: 2,
								color: "green",
							},
							data: roughOmega1,
						},
						{
							name: "ω2",
							showSymbol: false,
							type: "line",
							lineStyle: {
								width: 2,
								color: "blue",
							},
							data: roughOmega2,
						},
					],
				};

				dataPage.setOption(option);
			}, 20)
		},

		clearData(state) {
			state.roughTheta1 = [];
			state.roughOmega1 = [];
			state.roughTheta2 = [];
			state.roughOmega2 = [];
			state.innerBallPosition = [];
			state.outerBallPosition = [];
		},

		preview(state) {
			
			setTimeout(() => {
				
				var echarts = require("echarts");
				var previewArea = echarts.init(document.querySelector("#previewArea"));
				
				var l1 = state.l1;
				var l2 = state.l2;
				var theta1 = (state.initialTheta1 / 180) * Math.PI;
				var theta2 = (state.initialTheta2 / 180) * Math.PI;
				var r = 0.05 * (l1 + l2);
				
				var innerBallPosition = [l1 * Math.sin(theta1), -l1 * Math.cos(theta1)];
				var outerBallPosition = [
					l1 * Math.sin(theta1) + l2 * Math.sin(theta2),
					-l1 * Math.cos(theta1) - l2 * Math.cos(theta2),
				];
				var innerBallOutline = [];
				var outerBallOutline = [];
				
				var innerLine = [[0, 0], innerBallPosition];
				var outerLine = [innerBallPosition, outerBallPosition];
				
				for (var t = 0; t <= 2 * Math.PI; t += 0.01) {
					innerBallOutline.push([
						innerBallPosition[0] + r * Math.cos(t),
						innerBallPosition[1] + r * Math.sin(t),
					]);
					outerBallOutline.push([
						outerBallPosition[0] + r * Math.cos(t),
						outerBallPosition[1] + r * Math.sin(t),
					]);
				}
				
				var option = {
					animation: false,
					xAxis: {
						min: -1.05 * (l1 + l2),
						max: 1.05 * (l1 + l2),
						show: false,
					},
					yAxis: {
						min: -1.05 * (l1 + l2),
						max: 1.05 * (l1 + l2),
						show: false,
					},
					series: [
						{
							name: "innerLine",
							showSymbol: false,
							type: "line",
							lineStyle: {
								width: 3,
								color: "green",
							},
							data: innerLine,
						},
						{
							name: "innerBallOutline",
							showSymbol: false,
							type: "line",
							lineStyle: {
								width: 3,
								color: "red",
							},
							data: innerBallOutline,
						},
						{
							name: "outerLine",
							showSymbol: false,
							type: "line",
							lineStyle: {
								width: 3,
								color: "green",
							},
							data: outerLine,
						},
						{
							name: "outerBallOutline",
							showSymbol: false,
							type: "line",
							lineStyle: {
								width: 3,
								color: "orange",
							},
							data: outerBallOutline,
						},
					],
				};
				
				previewArea.setOption(option);
			}, 20)
		},
	},
	actions: {},
	modules: {}
})
